package com.ajview.core.web.exception;

import com.ajview.common.core.domain.enums.ResultCodeEnum;
import com.ajview.common.core.domain.vo.ResultVo;
import com.ajview.common.core.exception.ServiceGlobalException;
import com.ajview.common.core.exception.auth.AuthGlobalException;
import com.ajview.common.core.exception.auth.TokenCheckException;
import com.ajview.common.core.exception.base.BaseReponseException;
import com.alibaba.fastjson.JSONObject;
import io.lettuce.core.RedisConnectionException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.servlet.http.HttpServletRequest;

/**
 * @author ZhangJunJie
 * @Date 2022-04-27
 * <p>
 * 概要：全局异常处理
 * 对Controller进行增强的，可以全局捕获spring mvc抛的异常
 */
@Slf4j
@RestControllerAdvice
public class GlobalContextException {
    /**
     * 自定义全局业务异常
     */
    @ExceptionHandler(ServiceGlobalException.class)
    public JSONObject serviceGlobalException(ServiceGlobalException exception) {
        log.error("业务异常=>{}, 异常具体信息为: {}<-", exception.getMessage(), exception.toString());
        return ResultVo.result(exception.getCode(), exception.getMessage(), new JSONObject());
    }

    /**
     * 运行时异常
     *
     * @param exception
     * @return
     */
    @ExceptionHandler(RuntimeException.class)
    public JSONObject runtimeGlobalException(RuntimeException exception) {
        log.error("未知的运行时异常=>{}, 异常具体信息为: {} <-", exception.getMessage(), exception.toString());
        exception.printStackTrace();
        return ResultVo.error();
    }

    /**
     * 基础异常返回
     *
     * @param exception
     * @return
     */
    @ExceptionHandler(BaseReponseException.class)
    public JSONObject baseHandlerException(BaseReponseException exception) {
        log.error("自定义基础异常=>{}, 异常具体信息为: {} <-", exception.getE().getMessage(), exception.getE().toString());
        return ResultVo.error(exception.getMessage());
    }

    /**
     * 空指针异常进行统一处理
     *
     * @param e
     * @return
     */
    @ExceptionHandler(NullPointerException.class)
    public JSONObject nullPointerHandleException(NullPointerException e) {
        log.error("未处理的空指针异常=>{}，异常具体信息为：{}<-", e.getMessage(), e.toString());
        e.printStackTrace();
        return ResultVo.error();
    }

    /**
     * 系统异常，最大的异常进行统一返回处理
     */
    @ExceptionHandler(Exception.class)
    public JSONObject handleException(Exception e, HttpServletRequest request) {
        String requestURI = request.getRequestURI();
        log.error("请求地址'{}<-',发生未知的系统异常.", requestURI);
        e.printStackTrace();
        return ResultVo.error();
    }

    /**
     * 全局认证异常处理
     *
     * @param e
     * @return
     */
    @ExceptionHandler(AuthGlobalException.class)
    public JSONObject authHandleException(AuthGlobalException e) {
        log.error("认证失败，错误信息为 {}<-.", e.getMessage());
        return ResultVo.result(ResultCodeEnum.LOGIN_AUTH_EXCEPTION.getCode(), e.getMessage(), new JSONObject());
    }

    /**
     * 全局认证，非法请求方式，禁止访问系统资源
     *
     * @param e
     * @return
     */
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public JSONObject requestMethodNotSupported(HttpRequestMethodNotSupportedException e, HttpServletRequest request) {
        log.error("请求方式异常，请求url为 {},不支持{} 异常信息为{}", request.getRequestURI(), e.getMethod(), e.getMessage());
        return ResultVo.result(ResultCodeEnum.ILLEGAL_REQUEST_METHOD);
    }

    /**
     * token解析异常
     *
     * @param e
     * @return
     */
    @ExceptionHandler(TokenCheckException.class)
    public JSONObject tokenCheckException(TokenCheckException e) {
        log.error("token验证异常,{}。", e.getMessage());
        return ResultVo.result(e.getCode(), e.getMessage(), null);
    }

    /**
     * redis连接异常
     *
     * @param e
     * @return
     */
    @ExceptionHandler(RedisConnectionException.class)
    public JSONObject redisConnectionException(RedisConnectionException e, HttpServletRequest request) {
        log.error("redis连接异常,{}。", e.getMessage());
        return handleException(e, request);
    }

    /**
     * 参数校验统一异常处理
     *
     * @param ex
     * @return
     */
    @ExceptionHandler(BindException.class)
    public JSONObject bindExceptionHandler(BindException ex) {
        if (ex.hasErrors()) {
            StringBuffer sb = new StringBuffer("参数列表：");
            for (FieldError error : ex.getFieldErrors()) {
                sb.append(error.getField()).append(",");
                sb.append(error.getDefaultMessage()).append(";");
            }
            sb.append("不符合要求");
            return ResultVo.result(ResultCodeEnum.REQUEST_PARAMS_ERROR.getCode(), sb.toString(), new JSONObject());
        }
        return ResultVo.result(ResultCodeEnum.REQUEST_PARAMS_ERROR.getCode(), ex.getMessage(), new JSONObject());
    }


}
